package com.openspring.framework.extend.shiro;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.openspring.framework.util.JacksonUtils;

/**
 * 扩展FormAuthenticationFilter
 * 返回JSON以适应AJAX的应用
 * @author hebin
 *
 */
public class AjaxFormAuthenticationFilter extends FormAuthenticationFilter {

	private static final Logger log = LoggerFactory.getLogger(AjaxFormAuthenticationFilter.class);
	
	@Override
	protected boolean onAccessDenied(ServletRequest request,
			ServletResponse response) throws Exception {
		
		if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }
                return executeLogin(request, response);
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }
                //allow them to see the login page ;)
                return true;
            }
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
                        "Authentication url [" + getLoginUrl() + "]");
            }
            if(isAjax(request, response)) {
            	Map<String, Object> result = new HashMap<String, Object>();
            	result.put("success", false);
            	result.put("message", "用户未登陆或已过期");
            	response.setContentType("application/json;charset=" + request.getCharacterEncoding());
            	JacksonUtils.writerJson(response.getWriter(), result);
            } else 
            	saveRequestAndRedirectToLogin(request, response);
            return false;
        }
	}
	
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token,
			Subject subject, ServletRequest request, ServletResponse response)
			throws Exception {
		if(isAjax(request, response)) {
			Map<String, Object> result = new HashMap<String, Object>();
        	result.put("success", true);
        	response.setContentType("application/json;charset=" + request.getCharacterEncoding());
        	JacksonUtils.writerJson(response.getWriter(), result);
			return false;
		} else 
			return super.onLoginSuccess(token, subject, request, response);
	}

	@Override
	protected boolean onLoginFailure(AuthenticationToken token,
			AuthenticationException e, ServletRequest request,
			ServletResponse response) {
		if(isAjax(request, response)) {
			Map<String, Object> result = new HashMap<String, Object>();
        	result.put("success", false);
        	result.put("message", "登录失败,用户名或密码错误");
        	response.setContentType("application/json;charset=" + request.getCharacterEncoding());
        	try {
				JacksonUtils.writerJson(response.getWriter(), result);
			} catch (IOException e1) {
				log.error(e1.getMessage());
				throw new RuntimeException(e1);
			}
			return false;
		} else 
			return super.onLoginFailure(token, e, request, response);
	}
	
	public boolean isAjax(ServletRequest request, ServletResponse response) {
		String jsonHeader = WebUtils.toHttp(request).getHeader("accept");
		String xmlHeader = WebUtils.toHttp(request).getHeader("X-Requested-With");
		return (jsonHeader != null && jsonHeader.indexOf("application/json") > -1) || (xmlHeader != null && xmlHeader.indexOf("XMLHttpRequest") > -1);
	}
}
